<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />

    <title>Web Audio API examples: AudioParam</title>
  </head>

  <body>
    <h1>Web Audio API examples: AudioParam</h1>
    <audio controls>
      <source src="viper.ogg" type="audio/ogg" />
      <source src="viper.mp3" type="audio/mp3" />
      <p>This demo needs a browser supporting the &lt;audio&gt; element.</p>
    </audio>
    <div class="button-bar">
      <button class="set-target-at-time-plus">
        Set gain +0.25 in 1 second
      </button>
      <button class="set-target-at-time-minus">
        Set gain -0.25 in 1 second</button
      ><br />
      <button class="linear-ramp-plus">
        Linear ramp gain to 1 in 2 seconds
      </button>
      <button class="linear-ramp-minus">
        Linear ramp gain to 0 in 2 seconds</button
      ><br />
      <button class="exp-ramp-plus">
        Exponential ramp gain to 1 in 2 seconds
      </button>
      <button class="exp-ramp-minus">
        Exponential ramp gain to 0 in 2 seconds</button
      ><br />
      <button class="at-time-plus">Target at time 1 in 1s</button>
      <button class="at-time-minus">Target at time 0 in 1s</button><br />
      <button class="value-curve">Value curve</button>
    </div>
  </body>
  <script>
    let audioCtx;

    // set basic variables for example
    const audioElt = document.querySelector("audio");
    const pre = document.querySelector("pre");

    const targetAtTimePlus = document.querySelector(".set-target-at-time-plus");
    const targetAtTimeMinus = document.querySelector(
      ".set-target-at-time-minus"
    );
    const linearRampPlus = document.querySelector(".linear-ramp-plus");
    const linearRampMinus = document.querySelector(".linear-ramp-minus");
    const expRampPlus = document.querySelector(".exp-ramp-plus");
    const expRampMinus = document.querySelector(".exp-ramp-minus");
    const atTimePlus = document.querySelector(".at-time-plus");
    const atTimeMinus = document.querySelector(".at-time-minus");
    const valueCurve = document.querySelector(".value-curve");

    audioElt.addEventListener("play", () => {
      audioCtx = new AudioContext();

      // Create a MediaElementAudioSourceNode
      // Feed the HTMLMediaElement into it
      const source = new MediaElementAudioSourceNode(audioCtx, {
        mediaElement: audioElt,
      });

      // Create a gain node and set it's gain value to 0.5
      const gainNode = new GainNode(audioCtx, { gain: 0.5 });

      let currGain = gainNode.gain.value;

      // connect the AudioBufferSourceNode to the gainNode
      // and the gainNode to the destination
      source.connect(gainNode);
      gainNode.connect(audioCtx.destination);

      // set buttons to do something onclick
      targetAtTimePlus.onclick = () => {
        currGain += 0.25;
        gainNode.gain.setValueAtTime(currGain, audioCtx.currentTime + 1);
      };

      targetAtTimeMinus.onclick = () => {
        currGain -= 0.25;
        gainNode.gain.setValueAtTime(currGain, audioCtx.currentTime + 1);
      };

      linearRampPlus.onclick = () => {
        currGain = 1.0;
        gainNode.gain.linearRampToValueAtTime(1.0, audioCtx.currentTime + 2);
      };

      linearRampMinus.onclick = () => {
        currGain = 0;
        gainNode.gain.linearRampToValueAtTime(0, audioCtx.currentTime + 2);
      };

      expRampPlus.onclick = () => {
        currGain = 1.0;
        gainNode.gain.exponentialRampToValueAtTime(
          1.0,
          audioCtx.currentTime + 2
        );
      };

      expRampMinus.onclick = () => {
        currGain = 0;
        gainNode.gain.exponentialRampToValueAtTime(
          0.01,
          audioCtx.currentTime + 2
        );
      };

      atTimePlus.onclick = () => {
        currGain = 1.0;
        gainNode.gain.setTargetAtTime(1.0, audioCtx.currentTime + 1, 0.5);
      };

      atTimeMinus.onclick = () => {
        currGain = 0;
        gainNode.gain.setTargetAtTime(0, audioCtx.currentTime + 1, 0.5);
      };

      const waveArray = new Float32Array([0.5, 1, 0.5, 0, 0.5, 1, 0, 0.5]);
      valueCurve.onclick = () => {
        gainNode.gain.setValueCurveAtTime(waveArray, audioCtx.currentTime, 2);
      };
    });
  </script>
</html>
